package com.citycloud.ccuap.tc.admin.sec.secuser;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import com.citycloud.ccuap.commons.application.Application;
import com.citycloud.ccuap.commons.sys.group.IGroupService;
import com.citycloud.ccuap.commons.sys.repository.SysCodeRepository;
import com.citycloud.ccuap.framework.exception.ApplicationException;
import com.citycloud.ccuap.tc.admin.repository.SysDatagroupLevelRepository;
import com.citycloud.ccuap.tc.admin.repository.SysDatagroupRepository;
import com.citycloud.ccuap.tc.yq.constant.YqConstant;
import com.citycloud.ccuap.tc.yq.dto.FieldDTO;
import com.citycloud.ccuap.tc.yq.dto.TableDTO;
import com.citycloud.ccuap.tc.yq.entity.MetaBusType;
import com.citycloud.ccuap.tc.yq.entity.SysDimensionBustype;
import com.citycloud.ccuap.tc.yq.entity.SysResultSymbol;
import com.citycloud.ccuap.tc.yq.metafield.MetaFieldMapper;
import com.citycloud.ccuap.tc.yq.metatable.TableMapper;
import com.citycloud.ccuap.tc.yq.repository.MeatBusTypeRepository;
import com.citycloud.ccuap.tc.yq.repository.MetaFieldRepository;
import com.citycloud.ccuap.tc.yq.repository.MetaTableCateRepository;
import com.citycloud.ccuap.tc.yq.repository.MetaTableRepository;
import com.citycloud.ccuap.tc.yq.repository.SysDimensionBustypeRepository;
import com.citycloud.ccuap.tc.yq.repository.SysResultSymbolRepository;
import com.citycloud.ccuap.tc.yq.view.FieldWhere;
import com.citycloud.ccuap.tc.yq.view.Operator;
import com.citycloud.ccuap.tc.yq.view.TableField;

/**
 * 
 * @author liujianwei
 *
 */
@Service
public class UserRemoteService implements IUserRemoteService {

	private static Logger logger = LoggerFactory.getLogger(UserRemoteService.class);

	@Autowired
	SysDatagroupLevelRepository datagroupLevelDao;

	@Autowired
    SysCodeRepository codeDao;

	@Autowired
	MetaFieldRepository metaFieldDao;

	@Autowired
	MetaTableRepository tableDao;

	@Autowired
	SysDimensionBustypeRepository dimensuinBustypeDao;

	@Autowired
	MetaTableCateRepository metaTableCateRepository;

	@Autowired
	SysDatagroupRepository sysDatagroupRepository;

	@Resource
	@Lazy
	TableMapper tableMapper;

	@Resource
	@Lazy
	MetaFieldMapper fieldMapper;


	@Autowired
	MeatBusTypeRepository meatBusTypeRepository;


	@Autowired
	SysResultSymbolRepository sysResultSymbolRepository;

	@Autowired
	private IGroupService groupService;

	public List<FieldWhere> addFieldWhereMain(String bustypeObjId,
											  List<String> datagroups, FieldDTO field, List<String> hasInFieldId, String groupNo) {
		List<FieldWhere> fieldWheres=new ArrayList<>();
		Map<String, SysResultSymbol> resultSymbolMap = (Map<String, SysResultSymbol>) Application
				.getAttribute(YqConstant.RESULT_SYMBOL_KEY);
        List<SysDimensionBustype> dimensionBusTypeList=getSysDimensionBustype(bustypeObjId, datagroups);
		for (int i=0;i<dimensionBusTypeList.size();i++) {
			    SysDimensionBustype dimensionBusType=dimensionBusTypeList.get(i);
				String condition = null;
				String desc;
				SysResultSymbol symbol;
				// 默认类型为1、2、3、4时选择的组织机构，1、2需要获取当前userid的组织，3、4获取是前端传过来的需要进行多个条件like拼接
				switch (dimensionBusType.getSpecialType()) {
				// 当业务对象为组织且选择为“本机构”时
				case 1:
					// 建模只需要组织编号
					desc = groupNo;
					symbol = resultSymbolMap.get("39b4896f261011e595d802004c4f4f62");
					addFieldWhere(field.getEname(), symbol, desc, condition,
							dimensionBusType.getBustypeObjId(), fieldWheres, hasInFieldId);
					break;
				// 当业务对象为组织且选择为“本机构及下级机构”时
				case 2:
					desc = groupNo;
					if ("0000".equals(desc)) {
                        continue;
                    }
					desc = desc.substring(0, 2) + "%";
					symbol = resultSymbolMap.get("39b4896f261011e595d802004c4f4f68");

					 addFieldWhere(field.getEname(), symbol, desc, condition,
							dimensionBusType.getBustypeObjId(), fieldWheres, hasInFieldId);
					break;
				// 当业务对象为组织且选择为“其他机构及下级机构”时
				case 3:
					desc = dimensionBusType.getBustypeDescbak();
					if ("0000".equals(desc)) {
                        continue;
                    }
					String[] descArr = desc.split(",");
					if (descArr != null && descArr.length > 0) {
						for (String descTemp : descArr) {
							descTemp = descTemp.substring(0, 2) + "%";
							symbol = resultSymbolMap.get("39b4896f261011e595d802004c4f4f68");

							fieldWheres = addFieldWhere(field.getEname(), symbol, descTemp, condition,
									dimensionBusType.getBustypeObjId(), fieldWheres, hasInFieldId);
						}

					}
					break;
				// 默认选择的不是业务不是组织时,按常规处理
				default:
					condition = dimensionBusType.getBustypeCondition();
					desc = dimensionBusType.getBustypeDesc();
					symbol = resultSymbolMap.get(condition);

					if (symbol.getSymbolCode().contains("LIKE")) {
						desc = "%" + desc + "%";
					}
					addFieldWhere(field.getEname(), symbol, desc, condition,
							dimensionBusType.getBustypeObjId(), fieldWheres, hasInFieldId);
					break;
				}
		}
		return fieldWheres;
	}

	/**
	 * 以建值 字段名+条件+值进行判断是否已有此条件，有的话则不需要再次加入
	 */
	public List<FieldWhere> addFieldWhere(String ename, SysResultSymbol symbol, String desc, String condition,
			String datagroupId, List<FieldWhere> fieldWheres, List<String> hasInFieldId) {
		FieldWhere fieldWhere = new FieldWhere(ename, getOperator(symbol.getSymbolCode()), desc, datagroupId);
		if (!hasInFieldId.contains(fieldWhere.getFieldName() + condition + desc)) {
			fieldWheres.add(fieldWhere);
			// 以建值
			// 字段名+条件+值进行判断是否已有此条件，有的话则不需要再次加入
			hasInFieldId.add(fieldWhere.getFieldName() + condition + desc);

		}
		return fieldWheres;
	}

	
	private List<FieldDTO> getUserFields(String userId, String projectId, String datasource, String tableValue, List<String> datagroups) {
		List<FieldDTO> fieldList=new ArrayList<FieldDTO>();
		CopyOnWriteArrayList<TableDTO> tables=new CopyOnWriteArrayList<TableDTO>();
		for(int i=0;i<datagroups.size();i++) {
			//数据组获取表缓存
			List<TableDTO> list=tableMapper.getTableByDatagroupId(datagroups.get(i));
			tables.addAll(list);
		}
		Stream<TableDTO> stream = tables.stream().distinct();
		TableDTO tableDto=new TableDTO();
		if (StringUtils.isEmpty(datasource)) {
			tableDto = stream.filter(x -> {
				if (x.getTableId().equals(tableValue)) {
					return true;
				} else {
					return false;
				}
			}).findFirst().orElse(null);
		} else {
			tableDto = stream.filter(x -> {
				if (x.getDbId().equals(datasource) && x.getTableId().equals(tableValue)) {
					return true;
				} else {
					return false;
				}
			}).findFirst().orElse(null);
		}
		if(tableDto!=null) {
			fieldList=fieldMapper.getFieldByTableConfigId(tableDto.getTableConfigId());
		}
		return fieldList;
	}
	
	private List<String> getUserTables(String userId, String projectId, String datasource) {
		Stream<TableDTO> stream = cacheTable(userId, projectId);
		if (StringUtils.isEmpty(datasource)) {
			List<String> retUserTables = stream.map(x -> x.getTableId()).distinct().collect(Collectors.toList());

			return retUserTables;
		} else {
			List<String> retUserTables = stream.filter(x -> {
				if (x.getDbId().equals(datasource)) {
					return true;
				} else {
					return false;
				}
			}).map(x -> x.getTableId()).distinct().collect(Collectors.toList());
			
			return retUserTables;
		}
	}

	private Stream<TableDTO> cacheTable(String userId, String projectId) {
		//用户站点获取数据组缓存 
		List<String> datagroupList=fieldMapper.getDataGroup(userId, projectId);
		List<TableDTO> tables=new ArrayList<TableDTO>();
		for(int i=0;i<datagroupList.size();i++) {
			//数据组获取表缓存
			List<TableDTO> list=tableMapper.getTableByDatagroupId(datagroupList.get(i));
			tables.addAll(list);
		}
		Stream<TableDTO> stream = tables.stream().distinct();
		return stream;
	}

	
	private List<String> getUserFieldEnames(String userId, String projectId, String datasource, String tableValue) {
		Stream<TableDTO> stream = cacheTable(userId, projectId);
		TableDTO tableDto=stream.filter(x->x.getTableId().equals(tableValue)).findFirst().orElse(null);
		List<FieldDTO> list=new ArrayList<>();
		if(tableDto!=null) {
			list=fieldMapper.getFieldByTableConfigId(tableDto.getTableConfigId());
		}
		List<String> retUserFields = list.stream().map(x -> x.getEname()).distinct().collect(Collectors.toList());
		
		return retUserFields;
	}
	/**
	 * 获取用户指定表下拥有权限的字段 以及字段条件
	 */
	@Override
	public TableField getDataPermissionsOfTableField(String userId, String projectId, String datasource,
			String tableValue,String groupNo) {
		TableField reTableField = new TableField();
		try {
			List<String> datagroups=fieldMapper.getDataGroup(userId, projectId);
			List<FieldWhere> fieldWheres = new ArrayList<>();
			List<String> hasInFieldId = new ArrayList<>();

			List<FieldDTO> metaFieldList = getUserFields(userId, projectId, datasource, tableValue,datagroups);
			Map<String, MetaBusType> busTypeMap = (Map<String, MetaBusType>) Application
					.getAttribute(YqConstant.BUS_TYPE_MAP_KEY);
			List<String> enameList =metaFieldList.stream().map(x->x.getEname()).collect(Collectors.toList());
			metaFieldList.stream().filter(x->StringUtils.isNotEmpty(x.getBusType())&&busTypeMap.get(x.getBusType())!=null).forEach(metaField->{
				MetaBusType busType = busTypeMap.get(metaField.getBusType());
				String bustypeObjId = busType.getObjId();
				if (StringUtils.isNotBlank(bustypeObjId)) {
					fieldWheres.addAll(addFieldWhereMain(bustypeObjId,datagroups, metaField,
							hasInFieldId, groupNo));
				}
			});
			reTableField.setShowFields(enameList);
			reTableField.setFieldWheres(fieldWheres);

			return reTableField;
		} catch (Exception e) {
			logger.debug("获取用户指定表下拥有权限的字段 以及字段条件失敗", e);
			throw new ApplicationException("该获取用户指定表下拥有权限的字段 以及字段条件失敗！");
		}
	}

	/**
	 * 根据运算符获取运算符枚举类型 描述: <br>
	 * 1、…<br>
	 * 2、…<br>
	 *
	 * @param op
	 * @return
	 * @see
	 */
	private Operator getOperator(String op) {
		Operator operator = null;
		op = op.toLowerCase();
		switch (op) {
		case ">=": {
			operator = Operator.GREATERTHANEQUAL;
			break;
		}
		case ">": {
			operator = Operator.GREATERTHAN;
			break;
		}
		case "<=": {
			operator = Operator.LESSTHANEQUAL;
			break;
		}
		case "<": {
			operator = Operator.LESSTHAN;
			break;
		}
		case "like": {
			operator = Operator.LIKE;
			break;
		}
		case "<>": {
			operator = Operator.NOTEQUAL;
			break;
		}
		case "in": {
			operator = Operator.IN;
			break;
		}
		case "notlike": {
			operator = Operator.NOTLIKE;
			break;
		}
		default: {
			operator = Operator.EQUAL;
		}

		}
		return operator;
	}

	private List<SysDimensionBustype> getSysDimensionBustype(String bustypeObjId, List<String> datagroups) {
		List<SysDimensionBustype> list = dimensuinBustypeDao.getByBustypeObjId(bustypeObjId);
		List<SysDimensionBustype> bustypeList=new ArrayList<>();
		bustypeList=list.stream().filter(x->{
			String dataId = x.getDatagroupId();
			for (int i=0;i<datagroups.size();i++) {
				String id = datagroups.get(i);
				if (id.equals(dataId)) {
					return true;
				}
			}
			return false;
		}).collect(Collectors.toList());
		return bustypeList;
	}

	@Override
	public List<String> getDataPermissionsOfTableByUser(String userId, String projectId, String datasource) {
		List<String> list = getUserTables(userId, projectId, datasource);
		return list;
	}

	@Override
	public List<String> getDataPermissionsOfFieldByUserAndTable(String userId, String projectId, String datasource,
			String tableValue) {
		List<String> list = getUserFieldEnames(userId, projectId, datasource, tableValue);
		return list;
	}
	

	@Override
	public void cacheUserDataPermissions(String userId, String projectId) {
		fieldMapper.getDataGroup(userId, projectId);
	}

}
